package cc.rengu.oltp.utility.util;

/**
 * TLV数据操作工具类
 * Created by 王成 on 2017/12/21.
 */
public class TLVDataUtil {
    private final static String[] AFFIX = {"81", "81", "82", "83", "84"};

    /**
     * 生成TLV数据字符串
     *
     * @param tagKey   标签名
     * @param tagValue 标签值
     * @return TLV字符串
     */
    public static String packageTLVData(String tagKey, String tagValue) {
        StringBuilder tlvData = new StringBuilder();
        tlvData.append(tagKey);
        tlvData.append(generateTagValueLen(tagValue));
        tlvData.append(tagValue);
        return tlvData.toString().toUpperCase();
    }

    /**
     * 生成TAG值长度
     *
     * @param tagValue TAG标签值
     * @return TAG值长度字符串
     */
    public static String generateTagValueLen(String tagValue) {
        if (null == tagValue) {
            return "00";
        } else {
            String hexLength = Long.toHexString((tagValue.length() + 1) / 2);
            String valueLen = StringUtil.leftFillZero(hexLength, (hexLength.length() + 1) / 2 * 2);
            String prefix = AFFIX[valueLen.length() / 2];
            if ("81".equals(prefix)) {
                return valueLen.toUpperCase();
            } else {
                return (prefix + valueLen).toUpperCase();
            }
        }
    }

    /**
     * 这个方法能将ISO8583报文59域实际的数据内容解析能以正常人看懂的方式放入Map 取出 直接从标签开始解析 解析当前的t-l-v
     *
     * @param hexString
     *            传入的待解析的 ISO8583 报文域
     * @param all
     *            总数据量，此值不变，用于比较是否解析完成
     * @param count
     *            已解析的数据量
     * @param resultMap
     *            传入的 Map 容器，装载解析好的报文内容
     * @return resultMap 返回值
     */
	/*public static void getTLVMap(String hexString, Map<String, String> resultMap,int count, int all) {
		String nextHexString = hexString;
		// 记录传入字符串解析的位置
		int pos = 0;
		if (count != all) {
			// 根据银联终端规范截取该域当前标签以及该标签的数值长度
			String tag = getTag(nextHexString);
			pos += 2*2;
			Integer tagLength = getLength(nextHexString.substring(pos));
			pos +=3*2;
			// 去除当前标签和长度的报文
			String undecodeHexString = hexString.substring(pos,pos+tagLength*2);
			// 解析 v
			String value = decode(undecodeHexString);

			pos = pos + tagLength * 2;

			count += pos;
			// 将当前标签以 t 为 key v 为 v 装入Map
			resultMap.put(tag, value);

			// 解析下一个t-l-v
			getTLVMap(nextHexString.substring(pos), resultMap,count, all);

		}
		return ;

	}*/

    /**
     * @param nextHexString
     * @return String
     */
    public static String getTag(String nextHexString) {
        String tag = nextHexString.substring(0, 4);
        return tag;
    }

    /**
     * @param nextHexString 截取 Tag 之后的报文
     * @return int
     * 返回报文长度 十进制
     */
    public static Integer getLength(String nextHexString) {

        return Integer.valueOf(hexStringToString(nextHexString.substring(0, 3 * 2)));

    }

    /**
     *
     * @param
     *        bytes 待解析的字符串
     * @return String
     * 		解析之后的字符串
     */
	/*public static String decode(String bytes) {
		ByteArrayOutputStream baos = new ByteArrayOutputStream(
				bytes.length() / 2);
		// 将每2位16进制整数组装成一个字节
		String hexString = "0123456789ABCDEF";
		for (int i = 0; i < bytes.length(); i += 2) {
            baos.write((hexString.indexOf(bytes.charAt(i)) << 4 | hexString
                    .indexOf(bytes.charAt(i + 1))));

        }
		return new String(baos.toByteArray());
	}*/

    /**
     * 16进制字符串转换为字符串
     *
     * @param s
     * @return
     */
    public static String hexStringToString(String s) {
        if (s == null || "".equals(s)) {
            return null;
        }
        s = s.replace(" ", "");
        byte[] baKeyword = new byte[s.length() / 2];
        for (int i = 0; i < baKeyword.length; i++) {
            try {
                baKeyword[i] = (byte) (0xff & Integer.parseInt(
                        s.substring(i * 2, i * 2 + 2), 16));
            } catch (Exception e) {

            }
        }
        try {
            s = new String(baKeyword, "gbk");
            new String();
        } catch (Exception e1) {

        }
        return s;
    }
}
